/* Global BelMath */
MathHelper			= {}

/* Constants */
MathHelper.Inf		= 1 / 0
MathHelper.NaN		= 0 / 0

/* Linear interpolation */
function MathHelper.Lerp( delta, from, to )
	
	/* Ensure correct delta */
	if not IsNumber( delta ) then
		DEBUG:ErrMsg( "Invalid delta value '" .. tostring( delta ) .. "', must be a number between 0 and 1", "MathHelper.Lerp" )
		return false
	end
	
	/* Ensure valid objects */
	if ( not from and not IsBool( from ) ) or ( not to and not IsBool( to ) ) then
		DEBUG:ErrMsg( "At least one of the provided objects does not exist.", "MathHelper.Lerp" )
		return false
	end
	
	/* Ensure objects of equal type */
	if type( from ) != type( to ) then
		DEBUG:ErrMsg( "The given objects are not of the same type (" .. tostring( type( from ) ) .. " <> " .. tostring( type( to ) ) .. ").", "MathHelper.Lerp" )
		return false
	end
	
	/* Interpolate numbers */
	if IsNumber( from ) then
		
		/* Interpolate */
		return Lerp( delta, from, to )
	
	/* Interpolate tables */
	elseif IsTable( from ) then
		local ret = {}
		for k,v in pairs( from ) do
			ret[k] = MathHelper.Lerp( delta, from[k], to[k])
		end
		return ret
	
	/* Interpolate vectors */
	elseif IsVector( from ) then
		return LerpVector( delta, from, to ) -- ok, fine, this time I'll let you do it... ^^
	
	/* Interpolate angles */
	elseif IsAngle( from ) then	-- yeah, I had to create this one !
		return LerpAngle( delta, from, to )
	end
	
	/* No interpolation possible for the given objects type */
	DEBUG:ErrMsg( "No interpolation possible for type '" .. tostring( type( from ) ) .. "'.", "MathHelper.Lerp")
	return false
	
end

/* Linear interpolation */
function MathHelper.Round( value, decimals )
	
	/* Round number */
	if IsNumber( value ) then
		
		/* Interpolate */
		return math.Round( value, decimals )
	
	/* Round table */
	elseif IsTable( value ) then
		local ret = {}
		for k,v in pairs( value ) do
			ret[k] = MathHelper.Round( value[k], decimals )
		end
		return ret
	
	/* Round vectors */
	elseif IsVector( value ) then
		return Vector(
			math.Round( value.x, decimals ),
			math.Round( value.y, decimals ),
			math.Round( value.z, decimals )
		)
	
	/* Round angles */
	elseif IsAngle( value ) then
		return Angle(
			math.Round( value.p, decimals ),
			math.Round( value.y, decimals ),
			math.Round( value.r, decimals )
		)
	end
	
	/* No rounding possible for the given objects type */
	DEBUG:ErrMsg( "No rounding possible for type '" .. tostring( type( value ) ) .. "'.", "MathHelper.Round")
	return false
	
end

/* Clamp a table */
function MathHelper.ClampTable( value, min, max, clampLevel )
	
	/* Ensure valid table */
	if not IsTable( value ) then
		DEBUG:ErrMsg( "The given parameter is not a valid table.", "MathHelper.ClampTable" )
		return false
	end
	
	/* Min and max must be numbers */
	if not IsNumber( min ) or not IsNumber( max ) then
		DEBUG:ErrMsg( "The min and max parameters must be valid numbers.", "MathHelper.ClampTable" )
		return false
	end
	
	/* WTF can't you read you stupid nooob ??? Min means MIN and max means MAX, not the contrary you dumb *** ! */
	if min > max then
		DEBUG:ErrMsg( "The min parameter is greater than the max parameter.", "MathHelper.ClampTable" )
		return false
	end
	
	/* Return a clamped table */
	local ret	= {}
	for k,v in pairs( value ) do
	
		/* Clamp number */
		if IsNumber( v ) then
			ret[k]		= math.Clamp( v, min, max )
			
		/* Clamp child table */
		elseif IsTable( v ) then
		
			/* Check if we should dig deeper */
			local dig	= clampLevel and IsInt( clampLevel ) and clampLevel - 1 > 0
			if dig then
				ret[k]		= MathHelper.ClampTable( v, min, max, clampLevel - 1 )
			end
			
		/* This element is not "clampable" so just copy it */
		else
			ret[k]		= v
		end
	end
	return ret
end

/* Clamp a color */
function MathHelper.ClampColor( value )
	return MathHelper.ClampTable( value, 0, 255, 1 )
	-- return color.FromTable( MathHelper.ClampTable( color.ToTable( value ), 0, 255, 1 ) )
end

/* Ensure valid color */
function MathHelper.ValidateColor( value )
	return MathHelper.Round( MathHelper.ClampColor( value ), 0 )
end